package main.java.com.sloera.pool;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class FixedSizeThreadPool {

    //仓库
    private BlockingQueue<Runnable> taskQueue;

    //工作线程list worker重写线程
    private List<Worker> workers;

    //线程池的工作标识
    private volatile boolean working = true;

    public FixedSizeThreadPool(int poolSize, int taskQueueSize) {
        if (poolSize <= 0 || taskQueueSize <= 0) {
            throw new IllegalArgumentException("参数错误");
        }
        taskQueue = new LinkedBlockingQueue<>(taskQueueSize);

        workers = new ArrayList<>(poolSize);

        for (int i = 0; i < poolSize; i++) {
            Worker w = new Worker(this);
            //给当前线程池添加线程
            this.workers.add(w);
            w.start();

        }
    }

    public boolean submit(Runnable task) {
        if (this.working) {
            return this.taskQueue.offer(task);
        }
        return false;
    }

    public void shutdown() {
        this.working = false;
        //中断阻塞的线程
        for (Thread t : this.workers) {
            if (t.getState().equals(Thread.State.BLOCKED) || t.getState().equals(Thread.State.WAITING) || t.getState().equals(Thread.State.TIMED_WAITING)) {
                t.interrupt();
            }
        }
    }

    //重写线程对象
    private static class Worker extends Thread {
        FixedSizeThreadPool pool;

        public Worker(FixedSizeThreadPool pool) {
            this.pool = pool;
        }

        @Override
        public void run() {
            //TODO 循环从仓库中拿任务执行
            //super.run();
            int count = 0;
            Runnable task = null;
            //对于已提交任务，执行完后关闭
            while (this.pool.working || this.pool.taskQueue.size() > 0) {
                try {
                    //从仓库中取得需运行线程
                    if (this.pool.working) {
                        task = this.pool.taskQueue.take();
                    } else {
                        //调用shutdown后，不可用阻塞方式拿
                        task = this.pool.taskQueue.poll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (null != task) {
                    try {
                        //执行
                        task.run();
                        System.out.println(Thread.currentThread().getName() + "执行完" + (++count) + "个任务");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

    public static void main(String[] args) {
        //创建一个线程池
        FixedSizeThreadPool pool = new FixedSizeThreadPool(3, 6);
        for (int i = 0; i < 6; i++) {
            pool.submit(() -> {
                System.out.println("任务开始执行");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        pool.shutdown();
    }

}
